package com.example.demo.project.utils;




import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {

	public final static long ONE_SECOND_MS = 1000;
	public final static long ONE_MINUTE_MS = ONE_SECOND_MS * 60;
	public final static long ONE_HOUR_MS = ONE_MINUTE_MS * 60;
	public final static long ONE_DAY_MS = ONE_HOUR_MS * 24;

	public final static String EMPTY_STRING = "";

	private Utils () {
		throw new AssertionError(getClass() + "不需要实例化!");
	}

	/**
	 * 该方法用于判断含有可变长参数的方法其可变长参数是否最多仅有一个参数
	 * @param <P> 可变参数类型的父类类型
	 * @param <S> 可变参数类型
	 * @param variableParameters 可变参数的对象
	 * @return {@code variableParaemters[0]}或者 null
	 * @throws 
	 * <p><{@link IllegalArgumentException} 当参数VariableParaemters包含多个参数的时候</p>
	 */
	public static <P, S extends P> P emptyOrUnique(S[] variableParameters) {
		if (null == variableParameters || 0 == variableParameters.length) return null;
		if (1 < variableParameters.length) {
			IllegalArgumentException illegallArgumentException
			= new IllegalArgumentException("最多只支持一个参数");
			throw illegallArgumentException;
		} 
		return variableParameters[0];
	}



	/**
	 *
	 * @param <S>
	 * @param defaultValue
	 * @param candidateValue
	 * @return
	 */
	public static <S> S notNull(S defaultValue, S candidateValue) {
		if (null == defaultValue) {
			if (null == candidateValue) {
				throw new IllegalArgumentException("the defaultValue is null also");
			}
			return candidateValue;
		}
		return defaultValue;
	}



	/**
	 * 判断两个参数是否绝对相等，包含NULL值的比较
	 * @param <T> 
	 * @param obj1 
	 * @param obj2
	 * @return
	 */
	public static <T> boolean absEquals(T obj1, T obj2) {
		if (null == obj1) {
			return (null == obj2);
		}
		return obj1.equals(obj2);
	}



	public static String formatFileSize(long fileSize) {
		BigDecimal kb = BigDecimal.valueOf(fileSize >> 10);
		if (1024 > kb.doubleValue()) {
			return kb.toString() + "KB";
		} else {
			BigDecimal mb = kb.divide(BigDecimal.valueOf(1024), 1, BigDecimal.ROUND_HALF_UP);
			return mb.toString() + "MB";
		}
	}



	/**
	 * 获取class所在系统中的真实路径
	 * @param type
	 * @return
	 */
	public static Path getClassFileRealPath(Class<?> type) {



		/*	Path path = Paths.get(type.getProtectionDomain().getCodeSource().getLocation().getPath().replaceAll("^/", "").replaceAll("%20", " "));
		if (path.toString().endsWith("classes")) {
			path = path.resolve(type.getCanonicalName().replaceAll(".+?(\\.|$)", "../")).normalize();
		}
		path = path.resolve("../");
		return path;*/
		
		//上面注释部分代码在eclipse中调试得不到正确的类路径,故采用下面的方式获取类路径
		Path path  = Paths.get(type.getResource("").getPath().substring(1));
		return path;


	}

	public static void copyProperties(Object from, Object to) throws Exception {
		copyPropertiesExclude(from, to, null);
	}

	/**
	 * 复制对象属性
	 * @param from
	 * @param to
	 * @param excludsArray 排除属性列表
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception {
		List<String> excludesList = null;
		if(excludsArray != null && excludsArray.length > 0) {
			excludesList = Arrays.asList(excludsArray); //构造列表对象
		}
		Method[] fromMethods = from.getClass().getDeclaredMethods();
		Method[] toMethods = to.getClass().getDeclaredMethods();
		Method fromMethod = null, toMethod = null;
		String fromMethodName = null, toMethodName = null;
		for (int i = 0; i < fromMethods.length; i++) {
			fromMethod = fromMethods[i];
			fromMethodName = fromMethod.getName();
			if (!fromMethodName.contains("get"))
				continue;
			//排除列表检测
			if(excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) {
				continue;
			}
			toMethodName = "set" + fromMethodName.substring(3);
			toMethod = findMethodByName(toMethods, toMethodName);
			if (toMethod == null)
				continue;
			Object value = fromMethod.invoke(from, new Object[0]);
			if(value == null)
				continue;
			//集合类判空处理
			if(value instanceof Collection) {
				Collection newValue = (Collection)value;
				if(newValue.size() <= 0)
					continue;
			}
			toMethod.invoke(to, new Object[] {value});
		}
	}
	/**
	 * 从方法数组中获取指定名称的方法
	 *
	 * @param methods
	 * @param name
	 * @return
	 */
	public static Method findMethodByName(Method[] methods, String name) {
		for (int j = 0; j < methods.length; j++) {
			if (methods[j].getName().equals(name))
				return methods[j];
		}
		return null;
	}


}